// import 'dart:html';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:flutter/foundation.dart';

// import 'package:wanandroid_flutter/common/api.dart';
late HttpUtil instance;
bool hasInstance=false;
class HttpUtil {
  late Dio dio;
  late BaseOptions options;

  CancelToken cancelToken = CancelToken();
  static HttpUtil getInstance() {
    if(hasInstance) return instance;
    instance = HttpUtil();
    hasInstance=true;
    return instance;
  }

  /*
   * config it and create
   */
  HttpUtil() {
    //BaseOptions、Options、RequestOptions 都可以配置参数，优先级别依次递增，且可以根据优先级别覆盖参数
    options = BaseOptions(
      //请求基地址,可以包含子路径
      // baseUrl: host,
      //连接服务器超时时间，单位是毫秒.
      //connectTimeout: 10000,
      //响应流上前后两次接受到数据的间隔，单位为毫秒。
      //receiveTimeout: 5000,
      //Http请求头.
      headers: {
        // 移除可能导致CORS问题的自定义头
        // "version": "1.0.0"
      },
      //请求的Content-Type，默认值是"application/json; charset=utf-8",Headers.formUrlEncodedContentType会自动编码请求体.
      contentType: Headers.formUrlEncodedContentType,
      //表示期望以那种格式(方式)接受响应数据。接受四种类型 `json`, `stream`, `plain`, `bytes`. 默认值是 `json`,
      responseType: ResponseType.plain,
      // 允许携带Cookie
      extra: {'withCredentials': true}
    );

    dio = Dio(options);

    //Cookie管理 - 恢复平台检查，因为dio_cookie_manager不支持Web平台
    if (!kIsWeb) {
      var cookieJar = CookieJar();
      dio.interceptors.add(CookieManager(cookieJar));
    }

    // 添加CORS处理拦截器
    dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) {
        // 主动删除所有可能导致CORS问题的Access-Control-Allow-*请求头
        // 这些头信息应该由服务器在响应中设置，而不是客户端在请求中设置
        options.headers.removeWhere((key, value) => key.toLowerCase().contains('access-control-allow-'));
        return handler.next(options);
      },
      onResponse: (response, handler) {
        // 可以在这里记录接收到的Cookie信息
        print('Response cookies: ${response.headers['set-cookie']}');
        return handler.next(response);
      },
      onError: (DioError e, handler) {
        // 处理CORS相关错误
        if (e.response?.statusCode == 403 && e.response?.statusMessage?.contains('CORS') == true) {
          print('CORS error detected, trying alternative approach');
          // 可以在这里添加备用处理逻辑
        }
        return handler.next(e);
      },
    ));
  }

  /*
   * get请求
   */
  get(url, data, cb, errCallback) async {
    Response response;
    try {
      print("get-----------${url}");
      response = await dio.get(url,
          queryParameters:
              data); //, options: options, cancelToken: cancelToken);
      print('get success---------${response.statusCode}');
      print('get success---------${response.data}');
      cb(response.data);
      return response;
    } catch (e) {
      print('get error---------$e');
      if (e is DioException) {
        formatError(e);
      }
      if (errCallback != null) {
        errCallback(e);
      }
    }
    
  }

  /*
   * post请求
   */
  post(url, data, cb, errCallback) async {
    Response response;
    try {
      //Map<String,dynamic> map = Map();
      //map['userName']="小明";
      //map['userAge']=44;
      //FormData formData = FormData.fromMap(data);
      response = await dio.post(url, data: data,options: Options(contentType: Headers.jsonContentType));
      print('post success---------${response.data}');
      cb(response);
    } catch (e) {
      print('post error---------$e');
      if (e is DioException) {
        formatError(e);
      }
      if (errCallback != null) {
        errCallback(e);
      }
    }
  }

  put(url, data, cb, errCallback) async {
    Response response;
    try {
      response = await dio.put(url, data: data,options: Options(contentType: Headers.jsonContentType));
      print('post success---------${response.data}');
      cb(response);
    } catch (e) {
      print('post error---------$e');
      if (e is DioException) {
        formatError(e);
      }
      if (errCallback != null) {
        errCallback(e);
      }
    }
  }

  delete1(url, data, cb, errCallback) async {
    Response response;
    try {
      response = await dio.delete(url, data: data,options: Options(contentType: Headers.jsonContentType));
      print('post success---------${response.data}');
      cb(response);
    } catch (e) {
      print('post error---------$e');
      if (e is DioException) {
        formatError(e);
      }
      if (errCallback != null) {
        errCallback(e);
      }
    }
  }

  postForm(url, data, cb, errCallback) async {
    FormData formData = FormData.fromMap(data);
    Response response;
    try {
      response = await dio.post(url, data: formData);
      print('post success---------${response.data}');
      cb(response.data);
    } catch (e) {
      print('post error---------$e');
      if (e is DioException) {
        formatError(e);
      }
      if (errCallback != null) {
        errCallback(e);
      }
    }
  }

  /*
   * 下载文件
   */
  downloadFile(urlPath, savePath) async {
    Response response;
    try {
      response = await dio.download(urlPath, savePath,
          onReceiveProgress: (int count, int total) {
        //进度
        print("$count $total");
      });
      print('downloadFile success---------${response.data}');
      return response.data;
    } on DioException catch (e) {
      print('downloadFile error---------$e');
      formatError(e);
    }
  }

  /*
   * error统一处理
   */
  void formatError(DioException e) {
    print(e);
    // if (e.type == DioErrorType.CONNECT_TIMEOUT) {
    //   // It occurs when url is opened timeout.
    //   print("连接超时");
    // } else if (e.type == DioErrorType.SEND_TIMEOUT) {
    //   // It occurs when url is sent timeout.
    //   print("请求超时");
    // } else if (e.type == DioErrorType.RECEIVE_TIMEOUT) {
    //   //It occurs when receiving timeout
    //   print("响应超时");
    // } else if (e.type == DioErrorType.RESPONSE) {
    //   // When the server response, but with a incorrect status, such as 404, 503...
    //   print("出现异常");
    // } else if (e.type == DioErrorType.CANCEL) {
    //   // When the request is cancelled, dio will throw a error with this type.
    //   print("请求取消");
    // } else {
    //   //DEFAULT Default error type, Some other Error. In this case, you can read the DioError.error if it is not null.
    //   print("未知错误");
    // }
  }

  /*
   * 取消请求
   *
   * 同一个cancel token 可以用于多个请求，当一个cancel token取消时，所有使用该cancel token的请求都会被取消。
   * 所以参数可选
   */
  void cancelRequests(CancelToken token) {
    token.cancel("cancelled");
  }
}
